<?php

namespace eu\freeplace\core;

use eu\freeplace\core\Constants as Constants;
use PDO as PDO;

/**
 * Misc. Application Stuff.
 *
 * @author Elmar Dott
 * @version 1.0
 */
class Utils {

    const CLASS_NAME = "Utils";

    //Singelton Pattern =============================================
    static private $instance = null;
    static public function getInstance() {
        if (null === self::$instance) {
            self::$instance = new self;
        }
        return self::$instance;
    }
    /** Private Constructor implements a Singelton. */
    private function __construct() {
        global $logger;
        $logger->log("Calling instance of " . self::CLASS_NAME . "() [Singelton]", "NOTICE");
    }
    #================================================================

    #
    # CONVERTIONS
    #

    /**
     * Escapes HTML Entities.
     *
     * <a href="http://www.sample.org">sample.org</a>
     * will be converted to
     * &lt;a href="http://www.sample.org"&gt;sample.org&lt;/a&gt;
     *
     * @param String $string
     * @return $string
     */
    public function escapeHTML($string) {
        return htmlentities($string);
    }

    /**
     * The opposite of escapeHTML($string).
     *
     * @param String $string
     * @return $string
     */
    public function unescapeHTML($string) {
        return html_entity_decode($string, ENT_QUOTES);
    }

    #
    # FILE FUNCTIONS
    #

    /**
     * Read files from a Directory and allow to exclude some Files.
     *
     * @global Logger $logger
     * @param String $path
     * @param Array<String> $exclude
     * @return Array $files
     */
    public function readDir($path, $exclude="") {

        $cnt = 0; $cntJumps = 0;
        $cntExcludes = sizeof($exclude);
        $files = "";
        $directory = scandir($path);
        foreach ($directory as $file) {

            //excludes all dirs
            if (@!dir($file)) {

                //Exclude Files
                if($cntExcludes > 0) {
                    for($i=0; $i<$cntExcludes; $i++) {

                        if($file != $exclude[$i]) {
                            $files[$cnt] = $file;
                            $cnt++;
                        } else if($file == $exclude[$i]) {
                            $cntJumps++;
                        }
                    }//for
                } else {

                    $files[$cnt] = $file;
                    $cnt++;
                }//if-else
            }//if
        }//foreach

        global $logger;
        $logger->log(self::CLASS_NAME."().readDir(".$path.") - ".sizeof($files)." File(s) loaded & ".$cntJumps." Files ignored.", "DEBUG");

        return $files;
    }

    /**
     * Write XML content to a given File.
     *
     * @global Logger $logger
     * @param String $xmlStream
     * @param String $file
     */
    public function writeXMLFile($xmlStream, $fileName) {

        global $logger;
        $logger->log(self::CLASS_NAME."().writeXMLFile() - with ".sizeof($xmlStream)." Characters to file ".$fileName.".", "DEBUG");

        file_put_contents($fileName, $xmlStream->asXML());
    }


    #
    # Detectors
    #

    /**
     * Detect the current Operating System. Returns 'win' for a Windows OS,
     * 'linux' for others.
     *
     * @return String $OS
     */
    public function getOS() {
        $os_string = php_uname('s');
        if (strpos(strtoupper($os_string), 'WIN') !== false) {
            $os = 'windows';
        } else {
            $os = 'linux';
        }

        global $logger;
        $logger->log(self::CLASS_NAME . "().getOS(" . $os . ") detected", "DEBUG");

        return $os;
    }

    /**
     * Detect the Browser.
     *
     * @return String $browserType
     */
    public function getBrowserType() {

        $string = null;
        if (preg_match_all("#MSIE#i", $_SERVER['HTTP_USER_AGENT'], $string) != 0) {
            $browser = "ie";
        } else if (preg_match_all("#Opera#i", $_SERVER['HTTP_USER_AGENT'], $string) != 0) {
            $browser = "opera";
        } else if (preg_match_all("#Mozilla#i", $_SERVER['HTTP_USER_AGENT'], $string) != 0) {
            $browser = "mozilla";
        } else {
            $browser = null;
        }

        global $logger;
        $logger->log(self::CLASS_NAME . "().getBrowserType(" . $browser . ") detected", "DEBUG");

        return $browser;
    }

    /**
     * Detect the IP Adress of a client.
     *
     * @return IP
     */
    public function getIP() {

        $ip = $_SERVER['REMOTE_ADDR'];
        global $logger;
        $logger->log(self::CLASS_NAME . "().getIP(" . $ip . ")", "DEBUG");
        return $ip;
    }

    #
    # DATABASE
    #

    /**
     * Connection to a DATABASE.
     *
     * @global Logger $logger
     * @global Array $config
     * @return \banaalomedia\de\core\PDO
     * @throws Exception
     */
    public function connectDB() {

        global $logger;
        global $config;

        try {
            $dbh = "";
            $type = $config->core->database->dbms['value'];
            $host = $config->core->database->host['value'];
            $database = $config->core->database->db['value'];
            $user = $config->core->database->user['value'];
            $password = $config->core->database->pwd['value'];


            if ($type == "mysql") {
                $dbh = new PDO("mysql:host=" . $host . ";dbname=" . $database, $user, $password);
            } elseif ($type == "pgsql") {
                $dbh = new PDO("pgsql:dbname=" . $database . " host=" . $host, $user, $password);
            } else {
                $logger->log(self::CLASS_NAME . "().connectDB() - " . Constants::UTILS_EXCEPTION_DATABASE_TYPE, "ERROR");
                $dbh = new PDO("mysql:host=" . $host . ";dbname=" . $database, $user, $password);
            }

            $logger->log(self::CLASS_NAME . "().connectDB(database:" . $database . " type:" . $type . ", host:" . $host . ")", "DEBUG");
            return $dbh;
        } catch (PDOException $e) {
            $logger->log(self::CLASS_NAME . "().connectDB() - " . $e->getMessage(), "ERROR");
        }
    }

    public function closeDB($dbh) {

        global $logger;
        try {
            if ($dbh != null)
                $dbh = null;
            else
                throw new PDOException(Constants::UTILS_EXCEPTION_PDO);
        } catch (PDOException $e) {

            $logger->log(self::CLASS_NAME . "().connectDB() - " . $e->getMessage(), "ERROR");
        }

        $logger->log(self::CLASS_NAME . "().closeDB()", "DEBUG");
        return $dbh;
    }

    public function setResult($sql, $dbh) {
        try {
            $statement = $dbh->exec($sql);
            //Exception by empty SQL Result
            if ($statement == false) {
                throw new PDOException("Database Operation failed!");
            }
        } catch (PDOException $e) {
            $statement = $e->getMessage();
        }

        return $statement;
    }

    public function getResult($sql, $dbh) {
        try {
            $statement = $dbh->query($sql);
            //Exception by empty SQL Result
            if ($statement == false) {
                throw new PDOException("No Data fetched");
            }
        } catch (PDOException $e) {
            $statement = $e->getMessage();
        }
        return $statement;
    }

}//CLASS

?>